/*
NeverStar Games
*/

// You have to turn off Unicode!
// Click Projet on the menu, then Properties at the bottom
// (or hit Alt+F7)
// Click the General, Change Character Set 
// to "Use Multi-Byte Character Set"

#include <iostream>
#include <windows.h>
#include "DirectX.h"
// ADD THE REQUIRED DIRECTX PATHS FOR
// THE INCLUDES AND THE LIBRARIES!!!

using namespace std;

// global variables
// g_h - global handle - hungarian notation
HINSTANCE	g_hInst;	// handle to windows application instance
HWND		g_hWnd;		// handle to the window itself
CDirectX	g_DX;		// reference to DirectX object

// define global constants
#define WINDOW_CLASS	"TERMINAL CONNECTION GAME"
#define WINDOWED_MODE	true		//This is for windowed mode
//#define WINDOWED_MODE	false		//This is for full screen mode
#define SCREEN_WIDTH	1024
#define SCREEN_HEIGHT	768

// prototypes
void InitWindow();
LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);

/// Entry point to the application
int WINAPI WinMain(HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPTSTR lpCmdLine, 
				   int nCmdShow)
{
	// Put this code into the main to find memory leaks.
	// Run your app and then read the Output.
	// This code enables run-time memory check for debug builds
#if defined(DEBUG) | defined (_DEBUG)
	_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif

	// Store our application instance
	g_hInst = hInstance;

	// Initialize our window class and create the window
	InitWindow();

	// Initialize the DirectX object
	g_DX.Init( g_hWnd, g_hInst, SCREEN_WIDTH, SCREEN_HEIGHT, WINDOWED_MODE);

	// Calculate delta time based on cpu performance
	// - this way, the game runs at the same speed on all computers
	_int64 cyclesPerSec, prevTimeStamp, currTimeStamp;
	double secsPerCycle, dDeltaTime;	// Delta time variable based on cpu performance
	dDeltaTime = 0.0;	// Initialize

	// CPU frequency does not change so only poll once
	QueryPerformanceFrequency(( LARGE_INTEGER*)&cyclesPerSec);
	secsPerCycle = (double)( 1.0 / cyclesPerSec);

	// Get an initial time stamp
	QueryPerformanceCounter(( LARGE_INTEGER*)&prevTimeStamp);

	// Create a message structure
	MSG msg;
	ZeroMemory( &msg, sizeof(MSG));

	// Create the all important windows message loop
	while( msg.message != WM_QUIT)
	{
		// Process the windows messages
		if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage( &msg);  // translates to message codes
			DispatchMessage( &msg);	  // dispatch to correct places
		}

		// This is where we will run our game code EVERY frame
		g_DX.Update(g_hWnd, g_hInst, SCREEN_WIDTH, SCREEN_HEIGHT, (float)dDeltaTime);
		g_DX.Render((float)dDeltaTime);

		// Get second time stamp after we Update and Render
		QueryPerformanceCounter(( LARGE_INTEGER*)&currTimeStamp);

		// Calculate the delta time
		dDeltaTime = (currTimeStamp - prevTimeStamp) * secsPerCycle;

		// Set current time stamp to become the new previous time stamp
		prevTimeStamp = currTimeStamp;
	}

	// Shutdown / Destroy our DX class
	g_DX.Shutdown();

	// Unregister the window class
	UnregisterClass( WINDOW_CLASS, g_hInst);

	// Successful winmain!
	return 0;
}

/// Create and initialize our window
void InitWindow()
{
	// Create our window class structure
	WNDCLASSEX wndClass;
	ZeroMemory( &wndClass, sizeof(WNDCLASSEX));

	// Initialize variables of our window class structure
	wndClass.cbSize = sizeof(WNDCLASSEX);  // Size of window class structure
	wndClass.lpfnWndProc = (WNDPROC) WndProc;  // Our WndProc message handler
	wndClass.lpszClassName = WINDOW_CLASS;  // Class name string constant
	wndClass.hInstance = g_hInst;  // Handle to the application instance
	wndClass.hCursor = LoadCursor( NULL, IDC_ARROW); // Mouse Cursor
	wndClass.hbrBackground = (HBRUSH)COLOR_WINDOWFRAME; // Background brush

	// Register the window class with the Windows OS
	RegisterClassEx( &wndClass);

	// Create the window
	g_hWnd = CreateWindow(
		WINDOW_CLASS,	// Window class name
		WINDOW_CLASS,	// Window title bar string (can change)
		WINDOWED_MODE ? WS_OVERLAPPEDWINDOW : WS_EX_TOPMOST,	// Window mode
		//WS_EX_TOPMOST | WS_POPUP | WS_VISIBLE,				//Full screen mode
		CW_USEDEFAULT, CW_USEDEFAULT,  // Window postition (x, y)
		SCREEN_WIDTH, SCREEN_HEIGHT,  // Window size (w, h)
		NULL, NULL,  // Parent window, Menu
		g_hInst,	 // Handle to our application instance
		NULL);		 // Required but not used (backward compatibility)

	// Show and update our new window
	ShowWindow( g_hWnd, SW_SHOW);
	UpdateWindow( g_hWnd);
}

/// Custom Windows Procedure (event handler)
/// - messaging system (eg, moving mouse, pushing key, etc)
//  - you only have to check for the ones that you want
//  CALLBACK - you can use this function and pass it to another function
//		as a parameter
LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
	// Take appropriate action based on the event
	// that Windows gives us as a message number
	switch( message)
	{
	case WM_DESTROY:
		PostQuitMessage( 0);
		break;	
	}
	return DefWindowProc( hwnd, message, wparam, lparam);
}